import axios from 'axios';
import type { requestType } from "@/utils/request"
import { reactive, toRefs } from 'vue';
import type { ErrorData } from "@/utils/request"
import { memoize } from "lodash"

const key = Symbol('default');

export interface Options<P> {
  manual?: boolean; // 是否手动发起请求
  defaultParams?: P | any;
  isCache?: boolean; // 是否缓存函数结果
  isCancel?: boolean; // 开启取消请求 默认true
  repeatCancel?: boolean;  // 开启取消重复请求 保证此请求每次执行都将取消上一次任务并重新开启请求 默认true
}

export interface IRequestResult<T> {
  data: T | null;
  loading: boolean;
  err?: ErrorData;
}

const useRequest = <T, P>(
  api: requestType<T>,
  options: Options<P> = {
    defaultParams:{},
    manual : true,
    isCache : true,
    isCancel : true,
    repeatCancel : true,
  }
) => {

  const {
    manual,
    defaultParams,
    isCache,
    isCancel,
    repeatCancel
  } = options;

  let sourceToken = axios.CancelToken.source()

  const querise = reactive<Record<string | symbol, IRequestResult<T>>>({
    [key]: {
      data: null,
      loading: false,
    }
  });

  const service = async (args: P):Promise<T> => {

    // if(server.cache.get(args)) {
    //   return server.cache.get(args)
    // }
    try {
      if(repeatCancel) cancel()
      querise[key].loading = true

      const res = await api(args,isCancel ? {cancelToken: sourceToken.token} :{})
      if (res.code === 200) {
        querise[key].data = res.data
      } else {
        querise[key].err = {
          code: 501,
          msg: "请求失败",
          data: res.data
        }
      }
      // console.log('储存',args,server.cache.set(args,res.data));
      // server.cache.set(args,res.data)
      // console.log('缓存',server.cache.get(args));
      return res.data
    } catch (error) {
      querise[key].err = {
        code: 500,
        msg: "请求失败",
        data: error
      }
    } finally {
      querise[key].loading = false
    }
}
  const server = memoize(service,(a)=> String(a))

  const cancel = ()=>{
    sourceToken.cancel()
    sourceToken = axios.CancelToken.source()
  }

  const clearCache = ()=>{
    server.cache.clear()
  }

  if (!manual) {
    service(defaultParams)
  }

  return {
    service:isCache ? server : service,
    cancel,
    clearCache,
    ...toRefs(querise[key])
  }
}

export default useRequest
